package middleware

import (
	"github.com/gin-gonic/gin"
	"likeadmin/client/service/user"
	"likeadmin/config"
	"likeadmin/core"
	"likeadmin/core/response"
	clientModel "likeadmin/model/client"
	"likeadmin/util"
	"strconv"
	"strings"
)

var (
	userSrv = user.NewClientService(core.GetDB())
)

// TokenAuthClient Token认证中间件
func TokenAuthClient() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 路由转权限
		auths := strings.ReplaceAll(strings.Replace(c.Request.URL.Path, "/client/", "", 1), "/", ":")
		// 处理支付回调路由参数
		if strings.Contains(auths, "user:pay:notify:") {
			// 提取渠道参数
			pathParts := strings.Split(c.Request.URL.Path, "/")
			if len(pathParts) >= 5 && pathParts[3] == "pay" && pathParts[4] == "notify" {
				// 将动态参数路由转换为通用权限标识
				auths = "user:pay:notify:channel"
			}
		}
		// 免登录接口
		if util.ToolsUtil.Contains(config.ClientConfig.NotLoginUri, auths) {
			c.Next()
			return
		}

		// Token是否为空
		token := c.Request.Header.Get("token")
		if token == "" {
			response.Fail(c, response.TokenEmpty)
			c.Abort()
			return
		}

		// Token是否过期
		tokenKey := config.ClientConfig.BackstageTokenKey + token
		existCnt := util.RedisUtil.Exists(tokenKey)
		if existCnt < 0 {
			response.Fail(c, response.SystemError)
			c.Abort()
			return
		} else if existCnt == 0 {
			response.Fail(c, response.TokenInvalid)
			c.Abort()
			return
		}

		// 用户信息缓存
		uidStr := util.RedisUtil.Get(tokenKey)

		var uid uint
		if uidStr != "" {
			i, err := strconv.ParseUint(uidStr, 10, 32)
			if err != nil {
				core.Logger.Errorf("TokenAuth Atoi uidStr err: err=[%+v]", err)
				response.Fail(c, response.TokenInvalid)
				c.Abort()
				return
			}
			uid = uint(i)
		}

		// 如果用户信息不存在缓存中，则重新缓存
		if !util.RedisUtil.HExists(config.ClientConfig.BackstageManageKey, uidStr) {
			//err := userSrv.CacheAdminUserByUid(uid)
			//if err != nil {
			core.Logger.Errorf("CacheAdminUserByUid not has cache ")
			response.Fail(c, response.TokenInvalid)
			c.Abort()
			return
			//}
		}

		// 校验用户被删除
		userInfoStr := util.RedisUtil.HGet(config.ClientConfig.BackstageManageKey, uidStr)
		if userInfoStr == "" {
			core.Logger.Errorf("TokenAuth user info not found in cache: uid=[%d]", uid)
			response.Fail(c, response.SystemError)
			c.Abort()
			return
		}

		var mapping clientModel.ClientUser
		err := util.ToolsUtil.JsonToObj(userInfoStr, &mapping)
		if err != nil {
			core.Logger.Errorf("TokenAuth Unmarshal err: err=[%+v], data=[%s]", err, userInfoStr)
			response.Fail(c, response.SystemError)
			c.Abort()
			return
		}

		if mapping.IsDelete == 1 {
			util.RedisUtil.Del(tokenKey)
			util.RedisUtil.HDel(config.ClientConfig.BackstageManageKey, uidStr)
			response.Fail(c, response.TokenInvalid)
			c.Abort()
			return
		}

		// 校验用户被禁用
		if mapping.IsDisable == 1 {
			response.Fail(c, response.LoginDisableError)
			c.Abort()
			return
		}

		// 检查当前城市是否在屏蔽地区列表中
		black := util.FilterUtil.City([]string{}, mapping.CityInfo)

		// 如果命中屏蔽规则，则跳转至工具页面
		if black == false {
			c.Set("IsJump", "3")
		}

		// 令牌剩余30分钟自动续签
		if util.RedisUtil.TTL(tokenKey) < 1800 {
			util.RedisUtil.Expire(tokenKey, 7200)
		}

		// 单次请求信息保存
		c.Set(config.ClientConfig.ReqAdminIdKey, uid)
		c.Set(config.ClientConfig.ReqUsernameKey, mapping.Username)
		c.Set(config.ClientConfig.ReqNicknameKey, mapping.Nickname)

		c.Next()
	}
}
